﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommonUnity
{
    /// <summary>
    /// 计算表达式运算类   
    /// </summary>
    public class Calculate
    {
        /// <summary>   
        /// 获取中缀表达式   
        /// </summary>   
        /// <param name="exp">计算表达式（数字与运算符用空格分隔）</param>   
        /// <returns></returns>   
        public static List<string> getColuExpression(string exp)
        {
            System.Text.ASCIIEncoding asc = new System.Text.ASCIIEncoding();
            Stack st = new Stack();
            string[] temp = exp.Split(' ');
            List<string> value = new List<string>();

            for (int i = 0; i < temp.Length; i++)
            {
                int num = (int)asc.GetBytes(temp[i])[0];
                if (num < 48 && num > 39)
                {
                    if (st.Count > 0)
                    {
                        string operatorStr = st.Peek().ToString();
                        if (temp[i] == "*" || temp[i] == "/")
                        {
                            if (temp[i + 1] == "(")
                            {
                                st.Push(temp[i]);
                                continue;
                            }
                            else
                            {
                                if (operatorStr == "(")
                                {
                                    st.Push(temp[i]);
                                    continue;
                                }
                                else if (operatorStr == "*" || operatorStr == "/")
                                {
                                    value.Add(st.Pop().ToString());
                                    st.Push(temp[i]);
                                    continue;
                                }
                                else
                                {
                                    st.Push(temp[i]);
                                    continue;
                                }
                            }
                        }
                        else if (temp[i] == "+" || temp[i] == "-")
                        {
                            if (operatorStr == "(")
                            {
                                st.Push(temp[i]);
                                continue;
                            }
                            else
                            {
                                value.Add(st.Pop().ToString());
                                if (st.Count > 0 && st.Peek().ToString() != "(")
                                {
                                    value.Add(st.Pop().ToString());
                                }
                                st.Push(temp[i]);
                                continue;
                            }
                        }
                        else if (temp[i] == "(")
                        {
                            st.Push(temp[i]);
                            continue;
                        }
                        else
                        {
                            if (i + 1 == temp.Length)
                            {
                                value.Add(st.Pop().ToString());
                                st.Pop();
                                while (st.Count > 0)
                                    value.Add(st.Pop().ToString());
                                break;
                            }
                            else
                            {
                                value.Add(st.Pop().ToString());
                                st.Pop();
                                continue;
                            }
                        }
                    }
                    else
                    {
                        st.Push(temp[i]);
                        continue;
                    }
                }
                else if (i + 1 == temp.Length)
                {
                    value.Add(temp[i]);
                    value.Add(st.Pop().ToString());
                    while (st.Count > 0)
                        value.Add(st.Pop().ToString());
                    break;
                }
                else
                {
                    value.Add(temp[i]);
                    continue;
                }
            }
            return value;
        }

        /// <summary>   
        /// 获取计算表达式的值   
        /// </summary>   
        /// <param name="expression">中缀表达式数组</param>   
        /// <returns></returns>   
        public static decimal CalculateResult(string expre)
        {
            List<string> temp = getColuExpression(expre);
            try
            {
                while (temp.Count > 1)
                {
                    for (int i = 0; i < temp.Count; i++)
                    {
                        decimal resultTemp = 0;
                        if (temp[i] == "+")
                            resultTemp = Convert.ToDecimal(temp[i - 2]) + Convert.ToDecimal(temp[i - 1]);
                        else if (temp[i] == "-")
                            resultTemp = Convert.ToDecimal(temp[i - 2]) - Convert.ToDecimal(temp[i - 1]);
                        else if (temp[i] == "*")
                            resultTemp = Convert.ToDecimal(temp[i - 2]) * Convert.ToDecimal(temp[i - 1]);
                        else if (temp[i] == "/")
                            resultTemp = Convert.ToDecimal(temp[i - 2]) / Convert.ToDecimal(temp[i - 1]);
                        else
                            continue;
                        temp[i - 2] = resultTemp.ToString();
                        temp.RemoveAt(i);
                        temp.RemoveAt(i - 1);
                        break;
                    }
                }
            }
            catch (Exception ex)//计算表达式的值错误，导致无法运算   
            {
                temp.Clear();
                temp.Add("0");
            }
            return Convert.ToDecimal(temp[0]);
        }

    }
}
